var cursor_code = '<span id="cursor">&nbsp;</span>';
// this line will be appended each time the enter key pressed
var line = '<div class="line">terminal&nbsp;&gt;&nbsp;<span id="current">' + cursor_code + '</span></div>';

$(document).ready(function() {
    $("#term").append(line);
});


// updating the whole line from a given string
var update_cmd = function(str) {
    var str = str || "";
    var current_line = $("#current");
    
    if (str) {
        for (var i = 0; i < str.length; ++i) {
            current_line.append('<span>' + str[i] + '</span>');
        }
    }
    
    current_line.append(cursor_code);
};

var exclude = {'\n': true, '\t': true, ' ': true};

// appending a string for the current line
var append_cmd = function(str) {
    var str = str || "";
    var cursor = $("#cursor");
    
    var prev = false;
    
    if (str) {
        for (var i = 0; i < str.length; ++i) {
            if (!(str[i] in exclude)) {
                cursor.before('<span>' + str[i] + '</span>');
                prev = false;
            } else {
                // a number of spaces replacing with one
                if (!prev) {
                    cursor.before('<span>&nbsp;</span>');
                }
                
                prev = true;
            }
        }
    }
};

// history

var history_log = [];
var history_pos = -1;

var add_to_history = function(str) {
    str = $.trim(str)
    
    if (str.length > 0) {
        history_log.push(str);
        history_pos = history_log.length;
    }
};

var put_history = function(pos) {
    var current_line = $("#current");
    // removing all child nodes
    current_line.empty();
    //alert(history_log[pos]);
    update_cmd(history_log[pos]);
};

var prev_history = function() {
    if (history_pos >= -1) {
        history_pos--;
        put_history(history_pos);
    }
};

var next_history = function() {
    if (history_pos < history_log.length) {
        history_pos++;
        put_history(history_pos);
    }
};


var paste_data = function() {
    // hack for copying from the clipboad - 
    // temporarily copying the data into textarea container 
    // and then getting it from there
    var clip = $('#clip');
    clip.focus();
    // waiting until browser insert text to textarea
    window.setTimeout(function() {
        append_cmd(clip.val());
        clip.blur();
        clip.val('');
    }, 1);
};

// key presses handler


$(document).keypress(function(event) {
    var key = event.which;
    var term = $("#term");
    var cursor = $("#cursor");
    var current_line = $("#current");
    
    if (!event.ctrlKey) {
        switch (key) {
            case 13: { // enter
                cursor.removeAttr("id");
                
                // keeping the command in the history
                command = current_line.text();
                add_to_history(command);
                
                // reassigning the current line
                current_line.removeAttr("id");
                var app = null;
                // adding the typed command
                app = $('<div class="line">').text(command);
                term.append(app);
                
                // starting a new line
                app = line;
                term.append(app);
                
                break;
            }
            
            case 8: { // backspace
                var before = cursor.prev();
                before.remove(); 
                break;           
            }
            
            case 32: { // space
                cursor.before('<span>&nbsp;</span>');
                break;
            }
            
            case 0: { // arrows, F1-F12, del, etc
                var key_code = event.keyCode;
                switch (key_code) {
                    case 38: { // up arrow
                        prev_history();
                        break;
                    }
                    
                    case 40: { // down arrow
                        next_history();
                        break;
                    }
                    
                    case 37: { // left arrow
                        var before = cursor.prev();  
                        
                        if (before.length != 0) {
                            cursor.removeAttr("id");
                            before.attr("id", "cursor");
                        }
                        break;
                    }
                    
                    case 39: { // right arrow
                        var after = cursor.next();

                        if (after.length != 0) {
                            cursor.removeAttr("id");
                            after.attr("id", "cursor");     
                        }
                        break;
                    }
                    
                    case 46: { // delete
                        var after = cursor.next();
                        
                        if (after.length != 0) {
                            after.remove();   
                        }
                        break;
                    }
                    
                }
                break;
            }
            
            default: {
                app = String.fromCharCode(event.which);
                cursor.before('<span>' + app + '</span>');
                break;
            }
        }
    }
    
    if (event.ctrlKey) {
        if (key == 67 || key == 99) { // ctrl + c
            append_cmd("^C");
            cursor.removeAttr("id");
            current_line.removeAttr("id");
            term.append(line);
        } else if (key == 118 || key == 86) { // ctrl + v
            paste_data();
            return true;
        }
    }
    
    if (event.shiftKey) {
        if (event.keyCode == 45) { // shift_insert
            paste_data();
            return true;
        }
    }
    
    // scrolling down - TODO move out, but keep for now
    
    //var wrapper = $('#wrapper');
    //wrapper.scrollTop(wrapper.scrollHeight);
    // this code works better than jquery's
    var objDiv = document.getElementById("wrapper");
    objDiv.scrollTop = objDiv.scrollHeight;
    
    // for cauching f1-f12, ', etc.
    return false;
});

/*jQuery(document).bind('keydown', 'Shift+insert', function (evt) {
    paste_data(); 
    return true; 
});*/
